﻿// Copyright 2012 Jack Bulan (agentgeo)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using GemWorkshop.Formats.Nitro;

namespace GemWorkshop.Map
{
    public class MapSaver
    {
        private MapLoader m;

        public MapSaver(MapLoader ml)
        {
            m = ml;
        }

        public void Save(int header, int map)
        {
            // Save BIG header
            BinaryWriter bw = new BinaryWriter(File.OpenWrite(m.Arm9));
            bw.Seek(0xEEDBC + (header * 24), SeekOrigin.Begin); // Location in arm9

            bw.Write(m.Header.Textures);
            bw.Write(m.Header.ObjectTexutres);
            bw.Write(m.Header.Matrix);
            bw.Write(m.Header.Scripts);
            bw.Write(m.Header.Unknown1);
            bw.Write(m.Header.Texts);
            bw.Write(m.Header.MusicDay);
            bw.Write(m.Header.MusicNight);
            bw.Write(m.Header.WildPokemon);
            bw.Write(m.Header.Events);
            bw.Write(m.Header.Name);
            bw.Write(m.Header.Weather);
            bw.Write(m.Header.Camera);
            bw.Write(m.Header.NameStyle);
            bw.Write(m.Header.Flags);

            bw.Close();
            bw.Dispose();

            // Save map data header.
            MemoryStream mem = m.MapData.ExtractStream((uint)map);
            bw = new BinaryWriter(mem);

            bw.Write(m.MovementSize);
            bw.Write(m.ObjectSize);
            bw.Write(m.NSBMSize);
            bw.Write(m.BDHCSize);

            // Save movements.
            for (int y = 0; y < 32; y++)
            {
                for (int x = 0; x < 32; x++)
                {
                    bw.Write(m.Movements[x, y].Permission);
                    bw.Write(m.Movements[x, y].Flag);
                }
            }

            // Save objects.
            if (m.HasObjects)
            {
                for (int i = 0; i < m.Objects.Length; i++)
                {
                    bw.Write(m.Objects[i].Number);

                    bw.Write(m.Objects[i].XFlag);
                    if (m.Objects[i].X <= 16)
                        bw.Write((ushort)(m.Objects[i].X + 0xFFEF));
                    else
                        bw.Write((ushort)(m.Objects[i].X - 17));

                    bw.Write(m.Objects[i].YFlag);
                    bw.Write((ushort)m.Objects[i].Y);

                    bw.Write(m.Objects[i].ZFlag);
                    if (m.Objects[i].Z <= 16)
                        bw.Write((ushort)(m.Objects[i].Z + 0xFFEF));
                    else
                        bw.Write((ushort)(m.Objects[i].Z - 17));

                    for (int f = 0; f < 13; f++) // Filler
                        bw.Write((byte)0);

                    bw.Write(m.Objects[i].Width);
                    bw.Write(m.Objects[i].Height);
                    bw.Write(m.Objects[i].Length);

                    for (int f = 0; f < 7; f++) // Filler
                        bw.Write((byte)0);
                }
            }

            // TODO: Suicide :D
            // I'm still skipping this, because it's not neccessary (?)

            // Save to file.
            //NarcWriter nw = new NarcWriter(m.MapData);
            //nw.ReplaceFile((uint)map, mem);
            m.MapData.ReplaceFile((uint)map, mem);

            bw.Close();
            bw.Dispose();
            mem.Close();
            mem.Dispose();
        }
    }
}
